<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button>点击1</button>
    <button>点击哈哈哈</button>
    <button>点击</button>
    <button>点击</button>
    <button>点击123</button>
    <button>点击</button>
</body>
<script>
    // es6规范
    // 一.声明变量  var要求全部改用const  let
    // 1.var 导致变量提升的问题  污染全局变量
    // 2.使用var导致变量提升
    // 3.var可以被重复声明
    // 4.var作用域的问题

    // const 常量 不会变的量（地址不变即可）

    // 二.解构赋值
    // ...展开运算符 
    // 把两个数组合并一个数组
    // var arr1 = [1, 2, 3]
    // var arr2 = [4, 5, 6]
    // let arr3 = [...arr1, ...arr2]
    // 把两个对象合并一个对象
    // var school = { name: 'hmcuy' }
    // let my = { age: 18 }
    // var school = { name: 'hmcuy' }
    // let my = { age: { count: 18 }, name: 'jw' }
    // let newMy = { ...my, age: { ...my.count } }
    // let all = { ...school, ...newMy }
    // my.age.count = 100;
    // console.log(all)//count也变成了 100

    // 三.深拷贝（拷贝后无关） 浅拷贝（拷贝后有关）
    // var school = { name: 'hmcuy' }
    // let my = { age: { count: 18 }, name: 'jw' }
    // 把原来的my放在新对象里 里面新的age把原来的覆盖
    // let newMy = { ...my, age: { ...my.count } }
    // let all = { ...school, ...newMy }
    // my.age.count = 100;
    // ...只能拷贝一层

    // 方式2 把对象先转换为字符串  再把字符串转换成对象
    // var school = { name: 'hmcuy' }
    // let my = { age: { count: 18 }, name: 'jw' }

    // let all = JSON.parse(JSON.stringify({ ...school, ...my }));
    // my.age.count = 100;
    // console.log(all) //不会改变

    // 自己实现深拷贝的方法
    // function deepClone(obj, hash = new WeakMap()) {
    //     if (obj == null) return obj;
    //     if (obj instanceof Date) return new Date(obj);
    //     if (obj instanceof RegExp) return new RegExp(obj);
    //     if (typeof obj != 'object') return obj;
    //     // 判断是否有该值  递归引用
    //     if (hash.has(obj)) return hash.get(obj);
    //     var newObj = new obj.constructor;
    //     // 向对象里面添加
    //     hash.set(obj, newObj)
    //     for (var k in obj) {
    //         newObj[k] = deepClone(obj[k], hash)
    //     }
    //     return newObj
    // }
    // var obj = {
    //     name: 'zs',
    //     age: 14,
    //     sayhi: function () {
    //         alert(10)
    //     },
    //     school: {
    //         myschool: '定陶一中'
    //     }
    // }
    // obj.xxx = obj
    // var o = deepClone(obj);
    // // o.school.myschool = '曹县一种'
    // console.log(o)
    // console.log(obj)

    // 三.set（集合不能放重复的东西） and map 两种存储结构
    // var s = new Set([1, 2, 3, 4, 1, 2, 3, 4]);
    // console.log(typeof s)//对象 object
    // var arr = [...s] 数组去重
    // s.add(5)
    // s.delete(1)

    // 并集  交集  差集
    // let s1 = [1, 2, 3, 4, 1, 2, 6]
    // let s2 = [3, 4, 5, 1, 2]
    // 并集
    // function union() {
    //     var s01 = new Set(s1)
    //     var s02 = new Set(s2)
    //     // console.log([...new Set([...s01, ...s02])])
    // }
    // union()
    // 交集
    // function intersection() {
    //     // 返回true 表示留下
    //     var s = s1.filter(function (item) {
    //         return new Set(s2).has(item)
    //     })
    //     return [...new Set(s)]
    // }

    // console.log(intersection())
    // 差集
    // function diff() {
    //     // 返回true 表示留下
    //     var s = s1.filter(function (item) {
    //         return !new Set(s2).has(item)
    //     })
    //     return [...new Set(s)]
    // }

    // console.log(intersection())

    // map  保存的值有key
    // let m = new Map();
    // m.set('name', 'zfjg');
    // m.set('age', '123')
    // m.forEach(item => {
    //     console.log(item)
    // })

    // Object.defineProperty() es5 定义属性可以增加拦截器
    // 默认不可枚举
    // var obj = {}
    // var other = ''
    // Object.defineProperty(obj, 'name', {
    //     // value: 'hello',//赋值
    //     enumerable: true,//默认不可被枚举
    //     // configurable: true//是否可以被删除
    //     // writable: false//是否可以被重写
    //     get() {//读取方法
    //         console.log('----')
    //         return other
    //     },
    //     set(val) {//设置方法
    //         other = val
    //     }
    // })
    // obj.name = 'zs';
    // console.log(obj.name)
    // Vue的数据劫持
    // var obj = {
    //     name: 'chjy',
    //     age: 10,
    //     sex: 'nan',
    //     hobby: '篮球',
    //     address: {
    //         location: '回龙观'
    //     }
    // }

    // function update() {
    //     console.log('视图更新')
    // }


    // function Observe(obj) {
    //     if (typeof obj != 'object') return obj;
    //     for (var key in obj) {
    //         defineReactive(obj, key, obj[key])
    //     }
    // }

    // function defineReactive(obj, key, value) {
    //     Observe(value)
    //     Object.defineProperty(obj, key, {
    //         get() {
    //             return value
    //         },
    //         set(val) {
    //             update()
    //             value = val
    //         }
    //     })
    // }
    // Observe(obj)
    // // obj.name = 'zs'
    // // obj.age = 'zs'
    // obj.address = {
    //     location: '背景'
    // }
    // obj.address.location = '山东'
    // console.log(obj.address.location)

    // 箭头函数
    // var a = function (x, y) {
    //     return x + y
    // }
    // var a = (x, y) => {
    //     // return x + y
    // }
    // // var a = (x, y) => ({ res: x + y })
    // console.log(a(1, 2))
    // 箭头函数和this
    // let a = 1;
    // let obj = {
    //     a: 2,
    //     fn: function () {
    //         setTimeout(() => {
    //             console.log(this.a)
    //         }) 
    //     }
    // }
    // obj.fn()
    // 数组的一些方法
    // reduce常见用法： 多个数据最终变成一个数据
    // let res = [1, 2, 3, 4, 5].reduce((a, b) => {
    //     return a + b
    // })
    // let r = [0, { price: 100, count: 1 }, { price: 200, count: 2 }, { price: 300, count: 3 }].reduce((a, b) => {
    //     return a + b.price * b.count
    // })
    // let r = [{ price: 100, count: 1 }, { price: 200, count: 2 }, { price: 300, count: 3 }].reduce((a, b) => {
    //     return a + b.price * b.count
    // }, 0)
    // console.log(r)
    // let keys = ['name', 'age'];
    // let values = ['jw', 18];
    // let obj = keys.reduce((a, b, index) => {
    //     a[b] = values[index]
    //     return a
    // }, {})
    // console.log(obj)
    // 实现3个函数的封装 每个函数实现不同的功能
    // function sum(a, b) {
    //     return a + b
    // }
    // function toUpper(str) {
    //     return str.toUpperCase()
    // }
    // function add(str) {
    //     return '***' + str + "***"
    // }
    // // console.log(add(toUpper(sum('dfg', '666'))))
    // // 源码封装
    // function compose(...fns) {
    //     return function (...args) {
    //         let lastFn = fns.pop()
    //         return fns.reduceRight((a, b) => {
    //             return b(a)
    //         }, lastFn(...args))
    //     }
    // }
    // var res = compose(add, toUpper, sum)
    // console.log(res('dfg', 666))

    // 默认会先执行主栈中的代码  执行后去清空微任务
    // 之后微任务执行完毕  取出第一个宏任务到主栈执行
    // （如果有微任务在次去清空微任务） 再去执行宏任务
    // 形成事件环
    // 任务的执行
    // setTimeout(() => {
    //     console.log(1)
    //     Promise.resolve().then(data => {
    //         console.log(2)
    //     })
    // })
    // Promise.resolve().then(data => {
    //     console.log(3)
    //     setTimeout(() => {
    //         console.log(4)
    //     }, 0)
    // })
    // console.log('start')

    // 宏任务和微任务分类

    // function Animal(name) {
    //     this.name = name;
    //     this.arr = [1, 2, 3]
    // }
    // // consructor
    // Animal.prototype.address = { location: '山里' }
    // var a1 = new Animal('猴子')
    // var a2 = new Animal('小鸡')
    // console.log(a1.arr == a2.arr);//false
    // console.log(a1.address == a2.address)//true
    // console.log(a1.__proto__ == Animal.prototype)//true
    // console.log(a1.constructor == Animal)
    // console.log(Animal.__proto__==Function.prototype)

    // 类的继承
    // function Person() {
    //     this.name = name;
    //     this.hobby = '吃'
    // }
    // Person.prototype.address = { location: 'china' };

    // function Student(name) {
    //     this.name = name
    //     // 可以拿到父元素的属性 无法拿到方法
    //     Person.call(this)
    // }
    // 继承的方式 造成原型链的地址一样  不科学
    // Student.prototype = Person.prototype
    // Student.prototype.sayhi = function () {
    //     alert('student的sayhi')
    // }
    // Student.prototype.address = '自己的'
    // var s = new Student();
    // // s.sayhi()
    // // console.log(s.address)
    // var p = new Person();
    // // console.log(p.address);


    // 可以实现继承
    // Student.prototype.__proto__ = Person.prototype;
    // Student.prototype = Object.create(Person.prototype, { constructor: { value: Student } })
    // Student.prototype = create(Person.prototype)
    // Object.setPrototypeOf(Student.prototype, Person.prototype)

    // function create(parentprototype) {
    //     var fn = function () { };
    //     fn.prototype = parentprototype;
    //     var f = new fn();
    //     f.constructor = Student;
    //     return f;
    // }
    // var s = new Student();
    // Student.prototype.address = '自己的'
    // console.log(s.constructor)
    // var p = new Person();
    // console.log(p.address);


    // 函数  数组 对象 关系
    // function fn() {
    //     this.name = 'zs'
    //     this.age = 20
    // }
    // var F = new fn()

    // console.log(fn.__proto__.__proto__ == Object.prototype)
    // console.log(fn.__proto__.__proto__ == F.__proto__.__proto__)

    // var a = new Array()
    // var o = new Object()
    // console.log(Object.__proto__ == Function.prototype)
    // console.log(Object.getPrototypeOf(o))
    // // console.log('name' in F.__proto__)
    // console.log(F.__proto__.hasOwnProperty('name'))
    // console.log(Object.keys(F))

    // 类
    // class Person {
    //     constructor(name) {
    //         this.name = name
    //     }
    //     say() { //原型上的方法
    //         console.log('say')
    //     }
    // }
    // var p = new Person()
    // class Student extends Person {
    //     constructor(name) {
    //         super(name)
    //     }
    //     sayhi() {
    //         console.log(1234)
    //     }
    // }
    // var s = new Student()
    // 1.类不能当做函数调用
    // 2.es6 规定如果单独调用原型上的方法this不存在

    // var arr = [11, 22, 33, 44, 55];
    // var num = arr.forEach((item) => {
    //     return 5;
    // })
    // console.log(num)
    var arr = [11, 22, 33, 44, 55];
    // 把每一项和10相乘 返回数组 不改变原数组
    // var res = arr.map((item) => {
    //     return item * 10
    // })
    // console.log(res)
    // 返回满足条件的项 数组
    // var arr = [
    //     { id: 1, text: 'aa', done: true },
    //     { id: 2, text: 'bb', done: false }
    // ]
    // var res = arr.filter(function (item) {
    //     return item.done;
    // });
    // console.log(res)

    var arr = [
        { id: 1, text: 'aa', done: true },
        { id: 2, text: 'bb', done: false }
    ]
    console.log(arr.find(function (item, index, array) {
        console.log(1)
        return item.id == 1;
    }));


</script>

</html>